home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / util / gnu / GNU_OLEO_1_2_2.lha / oleo-1.2.2 / cells.c < prev    next >
C/C++ Source or Header  |  1993-03-03  |  11KB  |  581 lines

  1. /*    Copyright (C) 1990, 1992, 1993 Free Software Foundation, Inc.
  2.  
  3. This file is part of Oleo, the GNU Spreadsheet.
  4.  
  5. Oleo is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9.  
  10. Oleo is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with Oleo; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #define obstack_chunk_alloc ck_malloc
  20. #define obstack_chunk_free free
  21. #include "obstack.h"
  22. #include "funcdef.h"
  23. #include "sysdef.h"
  24.  
  25. #include "global.h"
  26. #include "cell.h"
  27. #include "eval.h"
  28. #include "errors.h"
  29. #include "lists.h"
  30.  
  31. struct value
  32.   {
  33.     int type;
  34.     union vals x;
  35.   };
  36.  
  37. #define Float    x.c_d
  38. #define String    x.c_s
  39. #define Int    x.c_l
  40. #define Value    x.c_i
  41. #define Rng    x.c_r
  42.  
  43. #define ERROR(x)    \
  44.  {            \
  45.     p->Value=x;    \
  46.     p->type=TYP_ERR;\
  47.     return;        \
  48.  }
  49.  
  50.  
  51. static int
  52. cell (row, col, dowhat, p)
  53.      long row;
  54.      long col;
  55.      char *dowhat;
  56.      struct value *p;
  57. {
  58.   struct func
  59.     {
  60.       char *name;
  61.       int typ;
  62.     };
  63.  
  64.   static struct func cell_funs[] =
  65.   {
  66.     {"row", TYP_INT},
  67.     {"column", TYP_INT},
  68.     {"width", TYP_INT},
  69.     {"lock", TYP_STR},
  70.     {"protection", TYP_STR},
  71.     {"justify", TYP_STR},
  72.     {"alignment", TYP_STR},
  73.     {"fmt", TYP_STR},
  74.     {"format", TYP_STR},
  75.     {"type", TYP_STR},
  76.     {"formula", TYP_STR},
  77.     {"value", 0},
  78.     {0, 0}
  79.   };
  80.  
  81.   CELL *cell_ptr;
  82.   char *strptr;
  83.   struct func *func;
  84.   struct func *f1;
  85.   int n;
  86.   extern default_lock;
  87.  
  88.   n = strlen (dowhat) - 1;
  89.   f1 = 0;
  90.   for (func = cell_funs; func->name; func++)
  91.     if (func->name[0] == dowhat[0]
  92.     && (n == 0 || !strincmp (&(func->name[1]), &dowhat[1], n)))
  93.       {
  94.     if (f1)
  95.       return BAD_INPUT;
  96.     f1 = func;
  97.       }
  98.   if (!f1)
  99.     return BAD_INPUT;
  100.   p->type = f1->typ;
  101.   switch (f1 - cell_funs)
  102.     {
  103.     case 0:
  104.       p->Int = row;
  105.       break;
  106.     case 1:
  107.       p->Int = col;
  108.       break;
  109.     case 2:
  110.       p->Int = get_width (col);
  111.       break;
  112.     case 3:
  113.     case 4:
  114.       p->String = ((cell_ptr = find_cell (row, col)) ? GET_LCK (cell_ptr) : default_lock) ? "locked" : "unlocked";
  115.       break;
  116.     case 5:
  117.     case 6:
  118.       p->String = jst_to_str ((cell_ptr = find_cell (row, col)) ? GET_JST (cell_ptr) : 0);
  119.       break;
  120.     case 7:
  121.     case 8:
  122.       p->String = fmt_to_str ((cell_ptr = find_cell (row, col)) ? GET_FMT (cell_ptr) : 0);
  123.       break;
  124.     case 9:
  125.       cell_ptr = find_cell (row, col);
  126.       if (cell_ptr)
  127.     switch (GET_TYP (cell_ptr))
  128.       {
  129.       case TYP_FLT:
  130.         p->String = "float";
  131.         break;
  132.       case TYP_INT:
  133.         p->String = "integer";
  134.         break;
  135.       case TYP_STR:
  136.         p->String = "string";
  137.         break;
  138.       case TYP_BOL:
  139.         p->String = "boolean";
  140.         break;
  141.       case TYP_ERR:
  142.         p->String = "error";
  143.         break;
  144.       default:
  145.         p->String = "unknown";
  146.       }
  147.       else
  148.     p->String = "null";
  149.       break;
  150.     case 10:
  151.       cell_ptr = find_cell (row, col);
  152.       if (cell_ptr && (GET_TYP (cell_ptr) || cell_ptr->cell_formula))
  153.     {
  154.       strptr = decomp (row, col, cell_ptr);
  155.       p->String = obstack_alloc (&tmp_mem, strlen (strptr) + 1);
  156.       strcpy (p->String, strptr);
  157.       decomp_free ();
  158.     }
  159.       else
  160.     p->String = "";
  161.       break;
  162.     case 11:
  163.       cell_ptr = find_cell (row, col);
  164.       if (cell_ptr)
  165.     {
  166.       p->type = GET_TYP (cell_ptr);
  167.       p->x = cell_ptr->c_z;
  168.     }
  169.       else
  170.     p->type = 0;
  171.       break;
  172.     default:
  173.       return BAD_INPUT;
  174.     }
  175.   return 0;
  176. }
  177.  
  178.  
  179. static void
  180. do_curcell (p)
  181.      struct value *p;
  182. {
  183.   extern CELLREF curow, cucol;
  184.   int tmp;
  185.  
  186.   tmp = cell (curow, cucol, p->String, p);
  187.   if (tmp)
  188.     ERROR (tmp);
  189. }
  190.  
  191. static void
  192. do_my (p)
  193.      struct value *p;
  194. {
  195.   int tmp;
  196.  
  197.   tmp = cell (cur_row, cur_col, p->String, p);
  198.   if (tmp)
  199.     ERROR (tmp);
  200. }
  201.  
  202. /* Note that the second argument may be *anything* including ERROR.  If it is
  203.    error, we find the first occurence of that ERROR in the range */
  204.  
  205. static void
  206. do_member (p)
  207.      struct value *p;
  208. {
  209.   CELLREF crow;
  210.   CELLREF ccol;
  211.   int foundit;
  212.   CELL *cell_ptr;
  213.  
  214.   find_cells_in_range (&(p->Rng));
  215.   while (cell_ptr = next_row_col_in_range (&crow, &ccol))
  216.     {
  217.       if (GET_TYP (cell_ptr) != (p + 1)->type)
  218.     continue;
  219.       switch ((p + 1)->type)
  220.     {
  221.     case 0:
  222.       foundit = 1;
  223.       break;
  224.     case TYP_FLT:
  225.       foundit = cell_ptr->cell_flt == (p + 1)->Float;
  226.       break;
  227.     case TYP_INT:
  228.       foundit = cell_ptr->cell_int == (p + 1)->Int;
  229.       break;
  230.     case TYP_STR:
  231.       foundit = !strcmp (cell_ptr->cell_str, (p + 1)->String);
  232.       break;
  233.     case TYP_BOL:
  234.       foundit = cell_ptr->cell_bol == (p + 1)->Value;
  235.       break;
  236.     case TYP_ERR:
  237.       foundit = cell_ptr->cell_err == (p + 1)->Value;
  238.       break;
  239. #ifdef TEST
  240.     default:
  241.       panic ("Unknown type (%d) in member", (p + 1)->type);
  242.       foundit = 0;
  243. #endif
  244.     }
  245.       if (foundit)
  246.     {
  247.       no_more_cells ();
  248.       p->Int = 1 + crow - p->Rng.lr + (ccol - p->Rng.lc) * (1 + p->Rng.hr - p->Rng.lr);
  249.       p->type = TYP_INT;
  250.       return;
  251.     }
  252.     }
  253.   p->Int = 0L;
  254.   p->type = TYP_INT;
  255. }
  256.  
  257. static void
  258. do_smember (p)
  259.      struct value *p;
  260. {
  261.   CELLREF crow;
  262.   CELLREF ccol;
  263.   CELL *cell_ptr;
  264.   char *string;
  265.  
  266.   string = (p + 1)->String;
  267.   find_cells_in_range (&(p->Rng));
  268.   while (cell_ptr = next_row_col_in_range (&crow, &ccol))
  269.     {
  270.       if ((GET_TYP (cell_ptr) == 0 && string[0] == '\0')
  271.       || (cell_ptr && GET_TYP (cell_ptr) == TYP_STR && strstr (string, cell_ptr->cell_str)))
  272.     {
  273.       no_more_cells ();
  274.       p->Int = 1 + (crow - p->Rng.lr)
  275.         + (ccol - p->Rng.lc) * (1 + (p->Rng.hr - p->Rng.lr));
  276.       p->type = TYP_INT;
  277.       return;
  278.     }
  279.     }
  280.   p->Int = 0L;
  281.   p->type = TYP_INT;
  282. }
  283.  
  284. static void
  285. do_members (p)
  286.      struct value *p;
  287. {
  288.   CELLREF crow;
  289.   CELLREF ccol;
  290.   CELL *cell_ptr;
  291.   char *string;
  292.  
  293.   string = (p + 1)->String;
  294.   find_cells_in_range (&(p->Rng));
  295.   while (cell_ptr = next_row_col_in_range (&crow, &ccol))
  296.     {
  297.       if (GET_TYP (cell_ptr) != TYP_STR)
  298.     continue;
  299.       if (strstr (cell_ptr->cell_str, string))
  300.     {
  301.       no_more_cells ();
  302.       p->Int = 1 + (crow - p->Rng.lr)
  303.         + (ccol - p->Rng.lc) * (1 + (p->Rng.hr - p->Rng.lr));
  304.       p->type = TYP_INT;
  305.       return;
  306.     }
  307.     }
  308.   p->Int = 0L;
  309.   p->type = TYP_INT;
  310. }
  311.  
  312. static void
  313. do_pmember (p)
  314.      struct value *p;
  315. {
  316.   CELLREF crow;
  317.   CELLREF ccol;
  318.   CELL *cell_ptr;
  319.   char *string;
  320.  
  321.   string = (p + 1)->String;
  322.   find_cells_in_range (&(p->Rng));
  323.   while (cell_ptr = next_row_col_in_range (&crow, &ccol))
  324.     {
  325.       if ((GET_TYP (cell_ptr) == 0 && string[0] == '\0')
  326.       || (cell_ptr && GET_TYP (cell_ptr) == TYP_STR && !strncmp (string, cell_ptr->cell_str, strlen (cell_ptr->cell_str))))
  327.     {
  328.       no_more_cells ();
  329.       p->Int = 1 + (crow - p->Rng.lr)
  330.         + (ccol - p->Rng.lc) * (1 + (p->Rng.hr - p->Rng.lr));
  331.       p->type = TYP_INT;
  332.       return;
  333.     }
  334.     }
  335.   p->Int = 0L;
  336.   p->type = TYP_INT;
  337. }
  338.  
  339. static void
  340. do_memberp (p)
  341.      struct value *p;
  342. {
  343.   CELLREF crow;
  344.   CELLREF ccol;
  345.   CELL *cell_ptr;
  346.   int tmp;
  347.   char *string;
  348.  
  349.   string = (p + 1)->String;
  350.   find_cells_in_range (&(p->Rng));
  351.   tmp = strlen (string);
  352.   while (cell_ptr = next_row_col_in_range (&crow, &ccol))
  353.     {
  354.       if (GET_TYP (cell_ptr) != TYP_STR)
  355.     continue;
  356.       if (!strncmp (cell_ptr->cell_str, string, tmp))
  357.     {
  358.       no_more_cells ();
  359.       p->Int = 1 + (crow - p->Rng.lr)
  360.         + (ccol - p->Rng.lc) * (1 + (p->Rng.hr - p->Rng.lr));
  361.       p->type = TYP_INT;
  362.       return;
  363.     }
  364.     }
  365.   p->Int = 0L;
  366.   p->type = TYP_INT;
  367. }
  368.  
  369. static void
  370. do_hlookup (p)
  371.      struct value *p;
  372. {
  373.  
  374.   struct rng *rng = &((p)->Rng);
  375.   double fltval = (p + 1)->Float;
  376.   long offset = (p + 2)->Int;
  377.  
  378.   CELL *cell_ptr;
  379.   double f;
  380.   CELLREF col;
  381.   CELLREF row;
  382.   char *strptr;
  383.  
  384.   row = rng->lr;
  385.   for (col = rng->lc; col <= rng->hc; col++)
  386.     {
  387.       if (!(cell_ptr = find_cell (row, col)))
  388.     ERROR (NON_NUMBER);
  389.       switch (GET_TYP (cell_ptr))
  390.     {
  391.     case TYP_FLT:
  392.       if (fltval < cell_ptr->cell_flt)
  393.         goto out;
  394.       break;
  395.     case TYP_INT:
  396.       if (fltval < cell_ptr->cell_int)
  397.         goto out;
  398.       break;
  399.     case TYP_STR:
  400.       strptr = cell_ptr->cell_str;
  401.       f = astof (&strptr);
  402.       if (!*strptr && fltval > f)
  403.         goto out;
  404.       else
  405.         ERROR (NON_NUMBER);
  406.     case 0:
  407.     case TYP_BOL:
  408.     case TYP_ERR:
  409.     default:
  410.       ERROR (NON_NUMBER);
  411.     }
  412.     }
  413. out:
  414.   if (col == rng->lc)
  415.     ERROR (OUT_OF_RANGE);
  416.   --col;
  417.   row = rng->lr + offset;
  418.   if (row > rng->hr)
  419.     ERROR (OUT_OF_RANGE);
  420.   cell_ptr = find_cell (row, col);
  421.   if (!cell_ptr)
  422.     {
  423.       p->type = 0;
  424.       p->Int = 0;
  425.     }
  426.   else
  427.     {
  428.       p->type = GET_TYP (cell_ptr);
  429.       p->x = cell_ptr->c_z;
  430.     }
  431. }
  432.  
  433. static void
  434. do_vlookup (p)
  435.      struct value *p;
  436. {
  437.  
  438.   struct rng *rng = &((p)->Rng);
  439.   double fltval = (p + 1)->Float;
  440.   long offset = (p + 2)->Int;
  441.  
  442.   CELL *cell_ptr;
  443.   double f;
  444.   CELLREF col;
  445.   CELLREF row;
  446.   char *strptr;
  447.  
  448.   col = rng->lc;
  449.   for (row = rng->lr; row <= rng->hr; row++)
  450.     {
  451.       if (!(cell_ptr = find_cell (row, col)))
  452.     ERROR (NON_NUMBER);
  453.       switch (GET_TYP (cell_ptr))
  454.     {
  455.     case TYP_FLT:
  456.       if (fltval < cell_ptr->cell_flt)
  457.         goto out;
  458.       break;
  459.     case TYP_INT:
  460.       if (fltval < cell_ptr->cell_int)
  461.         goto out;
  462.       break;
  463.     case TYP_STR:
  464.       strptr = cell_ptr->cell_str;
  465.       f = astof (&strptr);
  466.       if (!*strptr && fltval > f)
  467.         goto out;
  468.       else
  469.         ERROR (NON_NUMBER);
  470.     case 0:
  471.     case TYP_BOL:
  472.     case TYP_ERR:
  473.     default:
  474.       ERROR (NON_NUMBER);
  475.     }
  476.     }
  477. out:
  478.   if (row == rng->lr)
  479.     ERROR (OUT_OF_RANGE);
  480.   --row;
  481.   col = rng->lc + offset;
  482.   if (col > rng->hc)
  483.     ERROR (OUT_OF_RANGE);
  484.  
  485.   cell_ptr = find_cell (row, col);
  486.   if (!cell_ptr)
  487.     {
  488.       p->type = 0;
  489.       p->Int = 0;
  490.     }
  491.   else
  492.     {
  493.       p->type = GET_TYP (cell_ptr);
  494.       p->x = cell_ptr->c_z;
  495.     }
  496. }
  497.  
  498. static void
  499. do_vlookup_str (p)
  500.      struct value *p;
  501. {
  502.  
  503.   struct rng *rng = &((p)->Rng);
  504.   char * key = (p + 1)->String;
  505.   long offset = (p + 2)->Int;
  506.  
  507.   CELL *cell_ptr;
  508.   CELLREF col;
  509.   CELLREF row;
  510.  
  511.   col = rng->lc;
  512.   for (row = rng->lr; row <= rng->hr; row++)
  513.     {
  514.       if (!(cell_ptr = find_cell (row, col)))
  515.     ERROR (NON_NUMBER);
  516.       switch (GET_TYP (cell_ptr))
  517.     {
  518.     case TYP_STR:
  519.       if (!strcmp (key, cell_ptr->cell_str))
  520.         goto out;
  521.       break;
  522.     case 0:
  523.     case TYP_FLT:
  524.     case TYP_INT:
  525.     case TYP_BOL:
  526.     case TYP_ERR:
  527.     default:
  528.       ERROR (NON_NUMBER);
  529.     }
  530.     }
  531. out:
  532.   if (row > rng->hr)
  533.     ERROR (OUT_OF_RANGE);
  534.   col = rng->lc + offset;
  535.   if (col > rng->hc)
  536.     ERROR (OUT_OF_RANGE);
  537.  
  538.   cell_ptr = find_cell (row, col);
  539.   if (!cell_ptr)
  540.     {
  541.       p->type = 0;
  542.       p->Int = 0;
  543.     }
  544.   else
  545.     {
  546.       p->type = GET_TYP (cell_ptr);
  547.       p->x = cell_ptr->c_z;
  548.     }
  549. }
  550.  
  551.  
  552. static void
  553. do_cell (p)
  554.      struct value *p;
  555. {
  556.   int tmp;
  557.  
  558.   tmp = cell (p->Int, (p + 1)->Int, (p + 2)->String, p);
  559.   if (tmp)
  560.     ERROR (tmp);
  561. }
  562.  
  563. struct function cells_funs[] =
  564. {
  565.   {C_FN1 | C_T, X_A1, "S", do_curcell, "curcell"},
  566.   {C_FN1 | C_T, X_A1, "S", do_my, "my"},
  567.   {C_FN3 | C_T, X_A3, "IIS", do_cell, "cell"},
  568.  
  569.   {C_FN2, X_A2, "RA", do_member, "member"},
  570.   {C_FN2, X_A2, "RS", do_smember, "smember"},
  571.   {C_FN2, X_A2, "RS", do_members, "members"},
  572.   {C_FN2, X_A2, "RS", do_pmember, "pmember"},
  573.   {C_FN2, X_A2, "RS", do_memberp, "memberp"},
  574.  
  575.   {C_FN3, X_A3, "RFI", do_hlookup, "hlookup"},
  576.   {C_FN3, X_A3, "RFI", do_vlookup, "vlookup"},
  577.   {C_FN3, X_A3, "RSI", do_vlookup_str, "vlookup_str"},
  578.  
  579.   {0, 0, "", 0, 0},
  580. };
  581.